import os
import logging
from datetime import timedelta
from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
import pymysql
from dotenv import load_dotenv

load_dotenv()
logging.basicConfig(level=logging.INFO)

def get_db_conn():
    return pymysql.connect(
        host=os.getenv('DB_HOST', ''),
        port=int(os.getenv('DB_PORT', '')),
        user=os.getenv('DB_USER', 'root'),
        password=os.getenv('DB_PASSWORD', ''),
        database=os.getenv('DB_NAME', 'server-monitoring'),
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor,
        autocommit=True,
    )

app = Flask(__name__, static_folder='static', static_url_path='/static')
CORS(app)

def exec_query(sql, params=None):
    try:
        with get_db_conn() as conn:
            with conn.cursor() as cur:
                cur.execute(sql, params or ())
                return cur.fetchall()
    except Exception as e:
        logging.warning(f"DB query failed: {e}")
        # 优雅降级：返回空数组，前端仍可正常渲染页面
        return []

@app.route('/')
def index():
    return send_from_directory('static', 'index.html')

@app.route('/api/monitor/ips', methods=['GET'])
def get_ips():
    try:
        sql = "SELECT DISTINCT ip FROM system_monitor ORDER BY ip"
        rows = exec_query(sql)
        ips = [r.get('ip') for r in rows if r.get('ip')]
        return jsonify({"success": True, "data": ips})
    except Exception as e:
        logging.error(f"Error getting IPs: {e}")
        return jsonify({"success": False, "message": str(e), "data": []})

@app.route('/api/monitor/latest', methods=['GET'])
def latest_per_ip():
    try:
        ip = request.args.get('ip')
        if not ip:
            return jsonify({"success": False, "message": "IP parameter is required", "data": None})
        
        # 注意：schema中未包含 memoryUsage 字段，避免查询失败
        sql = (
            "SELECT ip, CPUUsage, diskUsage, monitor_time "
            "FROM system_monitor WHERE ip = %s "
            "ORDER BY monitor_time DESC LIMIT 1"
        )
        rows = exec_query(sql, (ip,))
        
        if not rows:
            return jsonify({"success": False, "message": "No data found for this IP", "data": None})
        
        row = rows[0]
        data = {
            "ip": row.get('ip'),
            "cpuUsage": row.get('CPUUsage'),
            "memoryUsage": None,  # 当前库无内存使用率字段
            "diskUsage": row.get('diskUsage'),
            "timestamp": row.get('monitor_time').strftime('%Y-%m-%d %H:%M:%S') if row.get('monitor_time') else None
        }
        
        return jsonify({"success": True, "data": data})
    except Exception as e:
        logging.error(f"Error getting latest data: {e}")
        return jsonify({"success": False, "message": str(e), "data": None})

@app.route('/api/monitor/recent', methods=['GET'])
def recent_alerts():
    minutes = int(request.args.get('minutes', '10'))
    cpu_ge = request.args.get('cpu_ge')
    disk_ge = request.args.get('disk_ge')
    ip = request.args.get('ip')

    conditions = ["monitor_time >= NOW() - INTERVAL %s MINUTE"]
    params = [minutes]
    if ip:
        conditions.append("ip = %s")
        params.append(ip)
    if cpu_ge is not None:
        conditions.append("CPUUsage >= %s")
        params.append(float(cpu_ge))
    if disk_ge is not None:
        conditions.append("diskUsage >= %s")
        params.append(float(disk_ge))

    where = " AND ".join(conditions)
    sql = f"SELECT * FROM system_monitor WHERE {where} ORDER BY monitor_time DESC"

    rows = exec_query(sql, params)
    return jsonify(rows)

@app.route('/api/monitor/trend', methods=['GET'])
def trend():
    ip = request.args.get('ip')
    hours = int(request.args.get('hours', '24'))
    if not ip:
        return jsonify({"error": "ip is required"}), 400

    sql = (
        "SELECT DATE_FORMAT(monitor_time, '%Y-%m-%d %H:00:00') AS bucket, "
        "AVG(CPUUsage) AS avg_cpu, AVG(diskUsage) AS avg_disk "
        "FROM system_monitor WHERE ip = %s AND monitor_time >= NOW() - INTERVAL %s HOUR "
        "GROUP BY bucket ORDER BY bucket"
    )
    rows = exec_query(sql, (ip, hours))
    return jsonify(rows)

@app.route('/api/monitor/gpu_trend', methods=['GET'])
def gpu_trend():
    try:
        ip = request.args.get('ip')
        days = int(request.args.get('days', '7'))
        
        if not ip:
            return jsonify({"success": False, "message": "IP parameter is required", "data": None})
        
        cols = []
        for i in range(8):
            cols.extend([f"gpu{i}name", f"gpu{i}m", f"gpu{i}mUsage"])
        select_cols = ", ".join(["monitor_time"] + cols)
        sql = (
            f"SELECT {select_cols} FROM system_monitor "
            "WHERE ip = %s AND monitor_time >= NOW() - INTERVAL %s DAY "
            "ORDER BY monitor_time ASC"
        )
        rows = exec_query(sql, (ip, days))
        
        if not rows:
            return jsonify({
                "success": True,
                "data": {"ip": ip, "days": days, "gpus": []}
            })
        
        # 构造每个 GPU 的序列
        gpus = []
        for i in range(8):
            series = []
            name = None
            mem  = None
            key_name = f"gpu{i}name"
            key_mem  = f"gpu{i}m"
            key_usage= f"gpu{i}mUsage"
            for r in rows:
                usage = r.get(key_usage)
                if r.get(key_name) and not name:
                    name = r.get(key_name)
                if r.get(key_mem) is not None and mem is None:
                    mem = r.get(key_mem)
                if usage is not None:
                    t = r.get('monitor_time')
                    t_str = t.isoformat(sep=' ', timespec='seconds') if hasattr(t, 'isoformat') else str(t)
                    series.append({"t": t_str, "v": float(usage)})
            if series:
                gpus.append({
                    "index": i,
                    "name": name or f"GPU {i}",
                    "memory_mb": mem,
                    "points": series
                })
        
        return jsonify({
            "success": True,
            "data": {"ip": ip, "days": days, "gpus": gpus}
        })
    except Exception as e:
        logging.error(f"Error getting GPU trend data: {e}")
        return jsonify({"success": False, "message": str(e), "data": None})

@app.errorhandler(Exception)
def handle_error(e):
    code = getattr(e, 'code', 500)
    return jsonify({"error": str(e)}), code

if __name__ == '__main__':
    port = int(os.getenv('PORT', '5000'))
    debug = os.getenv('DEBUG', 'false').lower() == 'true'
    app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=0)
    app.run(host='0.0.0.0', port=port, debug=debug)